{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "98fd95ce-17e8-46e4-b27a-698538c3c003",
   "metadata": {},
   "outputs": [],
   "source": [
    "from gs_quant.common import Currency, OptionType\n",
    "from gs_quant.markets import PricingContext\n",
    "from gs_quant.markets.portfolio import Portfolio\n",
    "from gs_quant.instrument import FXOption, FXForward\n",
    "from gs_quant.session import GsSession, Environment\n",
    "from gs_quant import risk"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3b2c11bd-c938-4852-b9db-86d4251453fd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# external users should substitute their client id and secret\n",
    "GsSession.use(Environment.PROD, client_id=None, client_secret=None, scopes=('run_analytics',))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1c97dffb-4d87-4063-81b5-73cdcd9305c1",
   "metadata": {},
   "outputs": [],
   "source": [
    "cross = \"GBPJPY\"\n",
    "premium_currency = Currency.GBP"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aeed27d1-dde1-499d-b288-bebc2dc8a06e",
   "metadata": {},
   "outputs": [],
   "source": [
    "option = FXOption(\n",
    "    cross,\n",
    "    expiration_date=\"2y\",\n",
    "    option_type=OptionType.Call,\n",
    "    strike_price=\"25d\",\n",
    "    premium_currency=premium_currency,\n",
    "    premium_payment_date=\"spot\",\n",
    ")\n",
    "option.resolve()\n",
    "# Here premium will have resolved to equal the option value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8dda27a5-9667-4e6f-9b40-d56e3d9b6acc",
   "metadata": {},
   "outputs": [],
   "source": [
    "spot = option.calc(risk.FXSpot)\n",
    "spot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2b5e92c6-72bc-40f7-b464-7357e01e8a4f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# The CSA terms for FX Fwds won't always be USD-OIS like for derrivs, so we force everything to USD-OIS to be consistent\n",
    "PricingContext.current = PricingContext(csa_term='USD-OIS')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "83146b2a-33c1-418c-99d1-4725edff74e9",
   "metadata": {
    "tags": [
     "Metrics - Black-Scholes Delta"
    ]
   },
   "source": [
    "### Black-Scholes Delta\n",
    "`FXQuotedDelta` will calculate Black-Scholes delta in % terms and is the delta metric that is used to solve if you specify the option strike in delta like above"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "736eccbb-12fe-4e33-8628-f102668f4711",
   "metadata": {},
   "outputs": [],
   "source": [
    "option.calc(risk.FXQuotedDelta)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "54966f17-18a0-4c24-8f60-6ff01d01f23e",
   "metadata": {
    "tags": [
     "Metrics - FXDelta"
    ]
   },
   "source": [
    "### Delta PnL\n",
    "The `FXDelta` measure captures the USD present value change from the move in spot rates for each USD cross (in normal convention). i.e. `PnL(USD) = dSpot * FXDelta`  \n",
    "Note: USD can be changed for another currency by parameterising the measure `FXDelta(currency='EUR')`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1be64972-841e-42f8-a7c2-b691e1272ece",
   "metadata": {},
   "outputs": [],
   "source": [
    "opt_fxdelta = option.calc(risk.FXDelta)\n",
    "opt_fxdelta.to_frame()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53871c7e-324e-4680-9f55-b30315b8f054",
   "metadata": {
    "tags": [
     "Metrics - Delta as Notional of fwd"
    ]
   },
   "source": [
    "### Delta as Notional of Fwd\n",
    "To compute the wing delta as the notional amount of an equivalent FX Fwd there are the measures `FXCalcDelta` and `FXDeltaHedge`.   \n",
    "`FXCalcDelta` returns a percentage factor of the option notional amount for the option cross.  \n",
    "`FXDeltaHedge` returns notional amounts of FX Fwds on USD crosses to hedge the option."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "afa2372f-3bed-4895-b82c-2ea5153b4438",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Here this will return a number close to the 0.25 B-S delta\n",
    "opt_fxcalc_notional = option.calc(risk.FXCalcDelta)\n",
    "opt_fxcalc_notional"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "99994eeb-757c-4031-a3fa-dfe7b3f509df",
   "metadata": {},
   "source": [
    "We can build the FXForward settling on spot date, with that `-1 * FXCalcDelta * notional` and check the FXDelta offsets, i.e. this is the spot trade on the option cross to hedge delta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f10b1365-c509-43af-9157-f4df14774d91",
   "metadata": {},
   "outputs": [],
   "source": [
    "fwd = FXForward(cross, \"0b\", \"f\", notional_amount=-1 * opt_fxcalc_notional * option.notional_amount)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "560ba96b-6da0-403c-8cd7-ebb95549fe0a",
   "metadata": {},
   "outputs": [],
   "source": [
    "fwd_risk = fwd.calc(risk.FXDelta)\n",
    "fwd_risk"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e360ec53-d58b-4fd5-b2b7-cf7d5eb84250",
   "metadata": {},
   "source": [
    "**Alternatively**: that hedge can be broken down into the two equivalent USDJPY and GBPUSD hedges, the `FXDeltaHedge` measure is already scaled by `-1 * option notional`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc44c7b8-4513-4fc4-966c-7821f1e561b7",
   "metadata": {},
   "outputs": [],
   "source": [
    "opt_fxhedge = option.calc(risk.FXDeltaHedge)\n",
    "opt_fxhedge"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a52955c-1d57-4fd0-ace4-5c8fc71ee878",
   "metadata": {},
   "outputs": [],
   "source": [
    "usd_fwds = [\n",
    "    FXForward(\n",
    "        opt_fxhedge.iloc[i].mkt_asset[4:] + opt_fxhedge.iloc[i].mkt_asset[:3], \"0b\", \"f\", opt_fxhedge.iloc[i].value\n",
    "    )\n",
    "    for i in range(len(opt_fxhedge))\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1ca8402b-d5ee-4607-a4f0-33323fbea298",
   "metadata": {},
   "outputs": [],
   "source": [
    "Portfolio(usd_fwds).calc(risk.FXDelta).aggregate()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  },
  "tags": [
   "Metrics - FX Delta Measures"
  ]
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
